package com.alibaba.middleware.race.sync;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.BufferUnderflowException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;

/**
 * 程序中使用的各种变量
 */
public class Constants2 {

    private static final Logger log = LoggerFactory.getLogger(Server.class);


    //提交代码的时候需要改为 false,
    public static final boolean isLocal = true;


    // server端口
    public static final Integer SERVER_PORT;

    public static final String HOME;

    // teamCode
    public static final String TEAM_CODE;

    //// 赛题数据：1.txt到10.txt
    public static final String DATA_HOME;

    //日志目录
    public static final String LOG_HOME;

    // 中间结果目录（client和server都会用到）
    public static final String MIDDLE_HOME;

    // 结果文件目录(client端会用到)
    public static final String RESULT_HOME;

    //结果文件的命名
    public static final String RESULT_FILE_NAME;

    //保存来自server端的结果
    public static final String SERVER_RESULT_FILE_NAME = "server_result.bin";

    static {
        if (isLocal) {
            SERVER_PORT = Constants.LOCAL_SERVER_PORT;
            HOME = Constants.LOCAL_HOME;
            TEAM_CODE = Constants.LOCAL_TEAM_CODE;
            DATA_HOME = Constants.LOCAL_DATA_HOME;
            LOG_HOME = Constants.LOCAL_LOG_HOME;
            MIDDLE_HOME = Constants.LOCAL_MIDDLE_HOME;
            RESULT_HOME = Constants.LOCAL_RESULT_HOME;
            RESULT_FILE_NAME = Constants.LOCAL_RESULT_FILE_NAME;

            System.out.println(TEAM_CODE);
            loadLogBackConfgFile("logback_local.xml");
        } else {
            SERVER_PORT = Constants.PROD_SERVER_PORT;
            HOME = Constants.PROD_HOME;
            TEAM_CODE = Constants.PROD_TEAM_CODE;
            DATA_HOME = Constants.PROD_DATA_HOME;
            LOG_HOME = Constants.PROD_LOG_HOME;
            MIDDLE_HOME = Constants.PROD_MIDDLE_HOME;
            RESULT_HOME = Constants.PROD_RESULT_HOME;
            RESULT_FILE_NAME = Constants.PROD_RESULT_FILE_NAME;
        }

        File dir = new File(DATA_HOME);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        dir = new File(LOG_HOME);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        dir = new File(MIDDLE_HOME);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        dir = new File(RESULT_HOME);
        if (!dir.exists()) {
            dir.mkdirs();
        }
    }

    //////////////////////////////

    public static String schema;

    public static String table;

    public static long pkStart;

    public static long pkEnd;

    public static final int pkBytes = 8;

    public static void readArgs(String[] args) {
        schema = args[0];
        table = args[1];
        pkStart = Long.parseLong(args[2]) + 1;
        pkEnd = Long.parseLong(args[3]) - 1;

        log.info("schema=" + schema + ",table=" + table + ",pkStart=" + pkStart + ",pkEnd=" + pkEnd);
    }


    ///////////////////////////////

    //server端处理的数据量和client处理的数据量的比重
    //会用 pkValue % 这个值 ，如果等于0，则交给client处理，否则server处理
    public static final int SERVER_DATA_WEIGHT = 2;

    //无符号byte能表示的最大值
    public static final int UNSIGNED_BYTE_MAX_VALUE = 255;

    //无符号short能表示的最大值
    public static final int UNSIGNED_SHORT_MAX_VALUE = 65535;

    //有符号3byte能表示的最大值
    public static final int SIGNED_3BYTE_MAX_VALUE = 8388607;

    //无符号3byte能表示的最大值
    public static final int UNSIGNED_3BYTE_MAX_VALUE = 16777215;

    //无符号int能表示的最大值
    public static final long UNSIGNED_INT_MAX_VALUE = 4294967295L;

    //如果发送给client的数据达到了这个量则进行网络传输，单位byte。(是指未压缩的数据量大小)
//    public static final int SEND_BUFFER_SIZE = 256;
    public static final int SEND_BUFFER_SIZE = 1024 * 1024;
//    public static final int SEND_BUFFER_SIZE = 10 * 1024 * 1024;

    public static void loadLogBackConfgFile(String externalConfigFileLocation) {
        /*try {
            LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
            JoranConfigurator configurator = new JoranConfigurator();
            configurator.setContext(lc);
            lc.reset();
            configurator.doConfigure(externalConfigFileLocation);
            StatusPrinter.printInCaseOfErrorsOrWarnings(lc);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }*/
    }


    public static int currFileIndex = 0;

    public static List<MappedByteBuffer> loadDataFile(int fileCount, boolean toPageCache) throws IOException {
        long s = System.currentTimeMillis();

        List<MappedByteBuffer> mbbs = new ArrayList<>(fileCount);
        byte[] $4k = new byte[4 * 1024];

        int i = 0;
        while (currFileIndex <= 10 && i++ < fileCount) {
            File file = new File(DATA_HOME, ++currFileIndex + ".txt");
            if (file.exists()) {
                RandomAccessFile raf = new RandomAccessFile(file, "r");
                raf.seek(raf.length() - 1);
                if (raf.readByte() != 10) {
                    raf.writeByte(10);
                }
                MappedByteBuffer mbb = raf.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, raf.length());

                if (toPageCache) {
                    try {
                        while (true) {
                            mbb.get($4k);
                        }
                    } catch (BufferUnderflowException e) {
                    }

                    while (mbb.hasRemaining()) {
                        mbb.get();
                    }
                    mbb.clear();
                }
                mbbs.add(mbb);
            }
        }

        if (toPageCache) {
            log.info("加载到pagecache耗时" + (System.currentTimeMillis() - s) + "ms");
        }
        return mbbs;
    }


    public static void printMiddleFiles() {
        /*File file = new File(MIDDLE_HOME);
        for (File file1 : file.listFiles()) {
            if (file1.isDirectory()) {
                continue;
            }
            log.info(file1.getName() + "   " + file1.length());
        }

        log.info("============================");*/
    }
}
